Перейти к основному содержимому

5.03. Прочие особенности языка Java

Разработчику Архитектору

Прочие особенности языка Java

Анонимные классы

Анонимный класс – это локальный внутренний класс без имени, который создаётся и используется сразу при объявлении. Он используется для реализации интерфейсов или абстрактных классов на лету, к примеру, при использовании слушателей событий, например, в GUI или коллбэках.

Пример:

interface Greeting {
void sayHello();
}

public class Main {
public static void main(String[] args) {
Greeting greet = new Greeting() {
public void sayHello() {
System.out.println("Hello from anonymous class!");
}
};

greet.sayHello();
}
}

Другой пример:

button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
}
});

Таким образом, анонимный класс — это безымянный внутренний класс, объявляемый и создающийся в момент использования.

Varargs

Varargs – методы с переменным числом аргументов.

Методы с переменным числом аргументов (varargs) принимают произвольное количество аргументов одного типа.

Пример:

public void printNumbers(int... numbers) {
for (int num : numbers) {
System.out.println(num);
}
}

Вызов:

printNumbers(1, 2, 3);
printNumbers();
printNumbers(new int[]{1, 2, 3});

То есть, varargs это в нашем случае numbers, который должен быть последним параметром в списке аргументов метода.

final

final – неизменяемость полей, методов и классов.

Если переменная объявлена как final, её значение нельзя изменить после инициализации.

final double PI = 3.14159;
PI = 3.14; // Ошибка компиляции

Для ссылочных типов нельзя изменить саму ссылку, но можно изменить состояние объектов:

final List<String> list = new ArrayList<>();
list.add("Hello"); // правильно
list = new ArrayList<>(); // неправильно

★ Метод, помеченный как final, нельзя переопределять в подклассе.

class Parent {
final void doNotOverride() {
System.out.println("This method cannot be overridden");
}
}

class Child extends Parent {
void doNotOverride() { } // Ошибка
}

Класс, объявленный как final, нельзя наследовать:

final class FinalClass { }

class SubClass extends FinalClass { } // Ошибка

this и super

this и super – работа с контекстом класса.

Ключевое слово this ссылается на текущий объект, может вызывать другой конструктор в том же классе – this(…);

this — это ссылка на текущий объект внутри его нестатического метода или конструктора.

Она используется, чтобы

  • сослаться на поля класса, если локальные переменные или параметры метода имеют такое же имя;
  • вызвать другой конструктор в том же классе;
  • передать текущий объект как аргумент другому методу или объекту.

Ключевое слово super ссылается на объект родительского класса, вызывает конструктор или метод родителя – super(…), как в примере выше.

Автоупаковка и автораспаковка

Автоупаковка (Autoboxing) – автоматическое преобразование значения типа-примитива (int, double, boolean) в соответствующий ему объект класса-обёртки (Integer, Double, Boolean).

Пример:

Integer number = 10; // int → Integer (автоупаковка)

Компилятор сам вызовет следующее:

Integer number = Integer.valueOf(10);

Автораспакова (Unboxing) – обратный процесс: автоматическое преобразование объекта класса-обёртки в примитивный тип. Пример:

Integer age = 25;
int primitiveAge = age; // Integer → int (автораспаковка)

Компилятор сам вызывает:

int primitiveAge = age.intValue();

Это используется в методах, принимающих или возвращающих обёртки, и при работе с коллекциями вроде:

List<Integer> numbers = new ArrayList<>();
numbers.add(5); // автоупаковка int → Integer

int x = numbers.get(0); // автораспаковка Integer → int

Но к коллекциям мы вернёмся позднее.

Безымянные пакеты

Безымянные пакеты. Пакеты содержат дополнительные возможности, для использования которых нужно добавлять их в код. Кроме того, как можно было заметить выше, в начале кода всегда была строчка:

package com.test.mavenproject1

Но что, если её не будет?

В таком случае (без строки package) класс автоматически попадает в безымянный (default, по умолчанию) пакет. Все классы без указания package находятся в одном общем безымянном пакете. Это удобно для простых примеров или тестирования, но в реальных проектах так делать нельзя – должен быть порядок. Для организации структуры проекта всегда нужно группировать всё по пакетам, и особенно если может быть конфликт имён. Современные IDE даже ругаются (запрещают) компилировать классы из безымянного пакета в модульных проектах (к примеру, Java Platform Module System).

Из безымянного пакета импортировать данные нельзя, следовательно, если будет класс:

public class Calculator {
public int add(int a, int b) {
return a + b;
}
}

…то как бы мы ни пытались:

import Calculator; //Ошибка
import .Calculator; //Тоже ошибка

Поэтому, импорт будет работать только с именованными пакетами, а класс должен быть в каком-то конкретном пакете.

Классы, находящиеся в одном пакете, могут обращаться друг к другу без использования оператора import – то есть видят друг друга напрямую. Если в разных пакетах – без импорта не обойтись.

Методы по умолчанию в интерфейсах

Методы по умолчанию (Default Methods) в интерфейсах появились в Java 8, и позволяют добавлять реализацию по умолчанию в интерфейс, не нарушая совместимость.

Пример:

interface Logger {
default void log(String message) {
System.out.println("Log: " + message);
}
}